#include <ctype.h>
#include <malloc.h>
#include <string.h>

#include "form.h"
#include "kmp.h"

static const char name_prefix[] = "Content-Disposition: form-data; name=\"";

Form* new_form()
{
    Form* form = make_form_node();
    form->tail = form;
    return form;
}

FormNode* make_form_node()
{
    FormNode* node = malloc(sizeof(FormNode));

    if (NULL == node) {
        fprintf(stderr, "[%s, %d]: Memory is not enouth.", __FILE__, __LINE__);
        return NULL;
    }

    node->next = NULL;
    node->tail = NULL;
    node->name_len = 0;
    node->value_len = 0;
    memset(node->name, 0, sizeof(node->name));
    memset(node->value, 0, sizeof(node->value));

    return node;
}

void append_form(Form* form, char name[], int name_len, char value[], int value_len)
{
    FormNode* node = make_form_node();

    strncpy(node->name, name, sizeof(node->name));
    strncpy(node->value, value, sizeof(node->value));
    node->name_len = name_len;
    node->value_len = value_len;

    form->tail->next = node;
    form->tail = node;
}

void delete_form(Form* form)
{
    if (NULL == form) {
        return;
    }

    FormNode* tmp;

    while (form != NULL) {
        tmp = form;
        form = form->next;
        free(tmp);
    }
}

Form* build_form(const char buf[], int len)
{
    Form* form = new_form();
    const int prefix_len = strlen(name_prefix);
    const char* p = buf;
    char name[MAX_NAME_LEN];
    char value[MAX_FIELD_LEN];
    int name_len, value_len;
    int next[prefix_len];
    int pos = 0;

    get_next(next, name_prefix, prefix_len);

    while (len > 0) {
        pos = kmp(p, len, name_prefix, prefix_len, next);

        if (pos < 0) {
            break;
        }

        p += pos + prefix_len; /* now p point to the first char of name */
        len -= pos + prefix_len;

        name_len = 0;
        while (*p != '"') {
            name[name_len++] = *p;
            ++p;
            --len;
        }
        name[name_len] = '\0';
        /* now p point to the right " */

        /* skip current line("\r\n) and next empty line(\r\n) */
        p += 5;
        len -= 5;

        /* now p point to the first char of value */

        value_len = 0;
        while (!iscntrl(*p)) {
            value[value_len++] = *p;
            ++p;
            --len;
        }
        value[value_len] = '\0';

        append_form(form, name, name_len, value, value_len);
    }

    return form;
}

void output_form(Form* form)
{
    while (form->next != NULL) {
        form = form->next;
        printf("[%s %s]\n", form->name, form->value);
    }
}
